import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.zip.Inflater;

/**
 * 数美SDK完整解密器 - Java版本
 * 基于真实返回值的反向工程
 * 
 * 核心假设：
 * 1. ep 字段使用 RSA-2048 加密，包含 AES 密钥和 IV
 * 2. data 和 tn 字段使用 AES-CBC 加密
 * 3. data 额外使用 zlib deflate 压缩
 */
public class ShumeiDecryptor {
    
    // ==================== 常量定义 ====================
    
    private static final String CERTIFICATE_BASE64 = 
        "MIIC6DCCAdCgAwIBAgIGAZlhQblOMA0GCSqGSIb3DQEBCwUAMDUxCzAJBgNVBAYTAkNO" +
        "MRAwDgYDVQQKEwdFeGFtcGxlMRQwEgYDVQQDEwtTZWxmLVNpZ25lZDAeFw0yNTA5MTkw" +
        "OTE1MjFaFw0yNjA5MTkwOTE1MjFaMDUxCzAJBgNVBAYTAkNOMRAwDgYDVQQKEwdFeGFt" +
        "cGxlMRQwEgYDVQQDEwtTZWxmLVNpZ25lZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC" +
        "AQoCggEBALPwnK6bMFFHWeN3E/MIWmpZesBQGILjJxNtMN1Z2lmRyLCJdTmz87EXmLuX" +
        "4e/Bz0aCOmH88qjs+laHFmnPIQal3rJU32MCMk63bejZN6yArwv8MAyF0kvyA3EoBC6Z" +
        "sYX55sxtxLyNYvG8MCqmacRbxV0IsSMXq6o4+1wOYiQEXzdbqhp67fYPNOv81LXqxQZA" +
        "rGV+Wj2o86XtW1wixtHnaSUori4jJjbe1YKi6LIbzhz9SK34+V4PkRhQYS7ensgAAbm4" +
        "k3N5R3RSNkOHLrHu576QaBwKYI1DjNJL9tAcySdqXColS9RLG0h/x2r78Pvybt3hm32f" +
        "1kPbu3hnaMcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEApMy1ilW+EsqQZ+2VMyvmQgjf" +
        "qoaat5kvNqdluLwtzISuY/dv1V2ccR3eShnta7hKO1WCT1WF3L31MLtDwWw/VEiWFDu3" +
        "+H/9P9nWr7w6ocGVWCUwUoZwiJk5DuBKZYlmj8LgjAKk6bh3hi7Fs3Kbct1rLXUtL0wi" +
        "qRF7y49tnjWKiEOzgIeHQnS6m2geS1aEpUQlsEm8vUanNuAmnWJppMpfJuWQ7XDPZfRD" +
        "elyepkefWSdOtd3RKKWGhk70KM00Scmav4mrUYE1K8xIXUvYrc2ECpyvuJjZ6masXzoT" +
        "RGN+bEvlOML/U6TTbXIttbqqnNe9iLrszUStBXjGkpJohA==";
    
    private static final String PRIVATE_KEY_PEM = 
        "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCz8JyumzBRR1nj" +
        "dxPzCFpqWXrAUBiC4ycTbTDdWdpZkciwiXU5s/OxF5i7l+Hvwc9Ggjph/PKo7PpW" +
        "hxZpzyEGpd6yVN9jAjJOt23o2TesgK8L/DAMhdJL8gNxKAQumbGF+ebMbcS8jWLx" +
        "vDAqpmnEW8VdCLEjF6uqOPtcDmIkBF83W6oaeu32DzTr/NS16sUGQKxlflo9qPOl" +
        "7VtcIsbR52klKK4uIyY23tWCouiyG84c/Uit+PleD5EYUGEu3p7IAAG5uJNzeUd0" +
        "UjZDhy6x7ue+kGgcCmCNQ4zSS/bQHMknalwqJUvUSxtIf8dq+/D78m7d4Zt9n9ZD" +
        "27t4Z2jHAgMBAAECggEAAr15RVdrpvE1NzeLADpyVghCzEbr+KJI6AzTn6tMneyQ" +
        "Z8/QDy7kWSAI3WJ0uFf1Nhepl/BoKZZiQYsRFk9nK1i/SWvtcu6HoZc9fzw/ksrq" +
        "333ZpXcsOqfW0ZRQa/0/LNEfaKGLS2vDw/afrSaXmbvkB4SoXeZwYMk5Wq+FYxL/" +
        "alrNpg/lzdvBlsCsTDA0G2RZrUVaO5yRTLRisBU+i8yORgnGkEwWvKpZYSFogCHS" +
        "iYHiNXFy//C+sYWlK7DjmG8/+krKhqBRRfdeg7LFThHQpbEGTtueD57jw0PCo2yr" +
        "6dqTvW9Qys+aWVNJk7RHNaI0yBFKWPadaHi3/olzkQKBgQDmz/FDpztS0fjKDIOj" +
        "gDyE76Z6dRFenmKJM1eOFt+MniY6/vi4ylU51/Etm4k6dNJ1MVBoFfyT9X0U/4k7" +
        "GNNUfIxMCJztUgY6EaCCt+09wk8pIvmOlRCmtxGwvmVC4nJVgUj3XJQ+wseblAkk" +
        "W0+IuT3GKX0CdKFMU4q9aucLYwKBgQDHk3rQ8Ae4ci4oj+MehRI29SNpcXG6OHbr" +
        "Z2EdsgqiFC1o/qv0269jtmCP7IqkGMdhTQrVetTHjZNZJH2bvUZ4o/0YT2+TTFPI" +
        "kTb2/a0txUTBTKrbnAdXh/iPFZAGvBROEDN0MNKo/vGAfi0K836DeTyBIaYongm6" +
        "6Rn6pwnUTQKBgBveVaougfoxAhIbSrWuISCH8xjsE6nSA+G/Aj5Uwq8u1TzgVlWx" +
        "kHLIgQVZt0sImfSufJ/kr7eJt42WgRJSoAmedC4mCBSbh8bxI+lEne+MC5TS9UDi" +
        "/Ly0c/1cL8vQna93ScEcO4YMbJ97U1NBdyvx+eR4U/C89lDJ8YGHa9gzAoGAQ6sY" +
        "sHFCXOKyDeTDoFyEUYgKqrzhT7/HaofR4Oy2OEBZKUl4anx2WnvC/+m3FG6mY7Jo" +
        "ovuT29mABXCe+khR9aO8tBpy/WGa4t2B4nse1e8WIehp4i5kOuSKfZFVFUN+Kv3J" +
        "RHMtakmO/v9JLHZlBhT8U9hh61GygOJ6gYdTiN0CgYAFz9iPy/xqLOUwiTNp3Imz" +
        "hdZo9ol3Qlr9CfMWMFHqRA5AyYvly9ZzxTpUCpSA+qz6OXqAjJ0bhGQxW2KHpmcT" +
        "yNGOPPca2vCaW8Mb1NTQueXpUBqX7alIkrRjUUyULteLb8FtyYl7mR3TVIu3FoO5" +
        "anNwDZ+2y7R9WUEiOzY3NA==";
    
    private static final String ORGANIZATION = "qvdTr7A9k1DIU04ha4eP";
    private static final String APP_ID = "default";
    private static final long TIMESTAMP = 1761287286183L;
    
    private static final String EP_ENCRYPTED = 
        "qt0AJsNLEfayUx7S15jLfmQvMOpW6JJ+jCoxeXxn676R2OiN6xpLIQWSYe8ETFUF4+Aa" +
        "GrVY1wMCdyUPVaHM0J+8m+q/PUFgbiP3N8xSKQc4lIzzZuckbybYiFuLbEhcblmy162S" +
        "5B70UJxzB6grhIVpsG/h0uw+JPaS2yTPpPVCiN/SImdOw2g12cun6niAwRZSQktZikzz" +
        "bjwkRoiO8ehrwlAFJircnT1/1zba2oaGXLc/yU6cM2vWgJdyyoXJF4Mo/5XNBTDT+8yr" +
        "1hPC5MKHWcTBB/isrRTD5CczInLgXHl48KKz18GkpPM7MML1GHb4pIjfTvu8hv/SLLW0sg==";
    
    private static final String TN_ENCRYPTED = 
        "BMWDCPVx97y8KsnGiff6u4lmEogvgO30LtR/QvfGyqQWadycCGkbGhL7jCKvJTHmlK0k" +
        "+fDR0XKq8U2IINpo0+aiWg8+nwaXQofOsilfXgDzG0DK9WJuwfcOrzGUHBn4yGVXDj+S" +
        "UklPWbq0fojYGLYendkSnSLYTzeYIusMyZ3HD2djXyUvekKz0cp39JgrD/Ovj2Nrwn4f" +
        "fPHcIXgSjpd02QXn4LNb4/7q465mfS2oQ5fRqiRMcnxpUhSD3Ty15bXVKJpPVqlqpM+t" +
        "cUcXVV4g7ggOux361BsPius8as1vd7wuK44EOJ56MJeATqROjECur2bWdftoWydjfZj5sw==";
    
    private static final String DATA_ENCRYPTED = 
        "wHBy2LDIay6WCgEybO8bw/5OxmVd4N++OJpwr/Tgjw+TA8iZ4HAy4bN8UWtwmeGz+dqU" +
        "/zX6myCireq+q465rqUqpXLhma2aEPqTaNvUTv/Y71kVpkMBkgrjMnVkIi/iBV5eKsrT" +
        "PfLWO8bt0mSbLM8ghswC2m2YRInkqWXHrc8Nw0JsNjwCllOUdtwe3NuIx8oQuQ2fqj1G" +
        "3g3xMp6B4sWBNAo+SjTNuKnS4chvbaD3RYnGvSLyNYu+sqbKeRNofCwVn0lVrjCAGtC9" +
        "d5nqhFiGw0vWksPfmCRn7vRsl7LnqcXb+Fal/hhREBsaRJdMrst3vOEeQI6pt3RGKZ3V" +
        "OsliNziKbLiNnXp2zY2fin32okAFwIOczPgeQA1yAM4FCnuT9FYAMn5ecAOY7WFhJPcO" +
        "qVThy0giCJrBzpIzEHXTin+BWBO1PR8wMzBqpf6us9mhBZGzu40mzVN34xXK646aMr8f" +
        "2DcD9yGO20v5icEz3OUcAeayMq+YKmBoypmvQUnaGa8pjr7RfvvajY+7pu6QHqRAQ3NL" +
        "Y1KjIoT3PKjabb7owQ1Txw5+Ajfjen7VEeF/Dq03nPMtNOpqD3tCdWDHWir+akJcEPtP" +
        "zK4Bo2K3FrLBZt2igZD6/04jtwoAojHibKqUM1Rj5h2iijH65eAU1XKTpqDPNtcP5lwa" +
        "1bFNV+GvuzHM+N4gcoxiELhQeG7xiUcsZrJvadkDO2z+If9vLkXTSdMKrqozUjLRapyX" +
        "pULcVL8negHnj+2vKZVdoGiDhXlm23XDFjLY91ZqX2eGfGNmpJxftl83N6q4dyXpzD2g" +
        "R/chHfm0CukVlL8P8aPAfEDcAsyQETc5oVLzetGVSkGBbQl+axZu8U2Ap9CXaTi1b2Vc" +
        "I3he19nvgG8XEFnwP6Tbicm5PDDsiRjo2MRqfuPLWkcSHTmBlS6w8yrzAvth9x/bBLg8" +
        "XLs8M/B/dKSfOa9sbptfTMmEuuhWbnqCyqnFSUt8lsFlcUbJdK02TcMbd789pANnrKTT" +
        "fFeOUehu5XReHng4DfV7f6boQmJPnZfwuR8qFwp7vwme235RTloktlkQu/2QFl2LmCv+" +
        "/8Za43dEdFba9Ae6I1p+50zunyIjGTE6/9RT+g/zgagzgV/qDDSM5VF6E2Ic62W/Kkpf" +
        "SPMHAk5Jwg0LlsSMnFXYCynZoDZ5M8s62V15VaEII3s/6wPCu4lba/BxPanRtw60EVsv" +
        "rJ7B0mnG+hcW8AGVeG1ZBIhgPH887/bY+05b0MnSkhjlrys8GKSaukVbtnrLJmjePt+L" +
        "dLe6tH2NTwxjbHhJR028ZWaQKvdC5BD2hRflDMBPKL68D6YJ2bitqnKKdEqYHdCMXtOX" +
        "h68XUqwfkoF3phQtYHyrqF4Wsgukf3/gAlt/yF0dXFTIUzoDTc34MEAaLFENVFDt4PUn" +
        "Yw2SRT8i/bhi3tcavu6Hnjs=";
    
    // ==================== 密钥派生策略 ====================
    
    /**
     * 密钥派生方案接口
     */
    interface KeyDerivationStrategy {
        byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception;
        String getName();
    }
    
    /**
     * IV派生方案接口
     */
    interface IvDerivationStrategy {
        byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception;
        String getName();
    }
    
    // 密钥派生方案实现
    static class KeyFromPublicKeyDER implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            byte[] publicKeyDER = cert.getPublicKey().getEncoded();
            return MessageDigest.getInstance("SHA-256").digest(publicKeyDER);
        }
        public String getName() { return "SHA256(公钥DER)"; }
    }
    
    static class KeyFromRSAModulus implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            RSAPublicKey publicKey = (RSAPublicKey) cert.getPublicKey();
            byte[] modulus = publicKey.getModulus().toByteArray();
            // 移除符号位
            if (modulus[0] == 0 && modulus.length > 256) {
                modulus = Arrays.copyOfRange(modulus, 1, modulus.length);
            }
            return MessageDigest.getInstance("SHA-256").digest(modulus);
        }
        public String getName() { return "SHA256(RSA模数)"; }
    }
    
    static class KeyFromCertFingerprint implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            byte[] certEncoded = cert.getEncoded();
            byte[] fingerprint = MessageDigest.getInstance("SHA-256").digest(certEncoded);
            return Arrays.copyOf(fingerprint, 32);
        }
        public String getName() { return "SHA256(证书指纹)"; }
    }
    
    static class KeyFromOrgAppId implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            String combined = org + ":" + appId;
            return MessageDigest.getInstance("SHA-256").digest(combined.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "SHA256(org:appId)"; }
    }
    
    static class KeyFromOrgOnly implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            return MessageDigest.getInstance("SHA-256").digest(org.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "SHA256(org)"; }
    }
    
    static class KeyFromCombined implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            baos.write(org.getBytes(StandardCharsets.UTF_8));
            baos.write(appId.getBytes(StandardCharsets.UTF_8));
            byte[] certData = cert.getEncoded();
            baos.write(Arrays.copyOf(certData, Math.min(64, certData.length)));
            return MessageDigest.getInstance("SHA-256").digest(baos.toByteArray());
        }
        public String getName() { return "SHA256(org+appId+cert64)"; }
    }
    
    static class KeyFromCertBytes implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            byte[] certData = cert.getEncoded();
            return Arrays.copyOf(certData, 32);
        }
        public String getName() { return "证书前32字节"; }
    }
    
    static class KeyFromMD5Double implements KeyDerivationStrategy {
        public byte[] deriveKey(X509Certificate cert, String org, String appId) throws Exception {
            String combined = org + ":" + appId;
            byte[] md5 = MessageDigest.getInstance("MD5").digest(combined.getBytes(StandardCharsets.UTF_8));
            byte[] key = new byte[32];
            System.arraycopy(md5, 0, key, 0, 16);
            System.arraycopy(md5, 0, key, 16, 16);
            return key;
        }
        public String getName() { return "MD5(org:appId)x2"; }
    }
    
    // IV派生方案实现
    static class IvFromTimestamp implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            return MessageDigest.getInstance("MD5").digest(String.valueOf(timestamp).getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "MD5(timestamp)"; }
    }
    
    static class IvFromTimestampField implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            String combined = fieldType + ":" + timestamp;
            return MessageDigest.getInstance("MD5").digest(combined.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "MD5(field:timestamp)"; }
    }
    
    static class IvFromTimestampOrg implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            String combined = timestamp + ":" + org;
            return MessageDigest.getInstance("MD5").digest(combined.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "MD5(timestamp:org)"; }
    }
    
    static class IvFromOrg implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            return MessageDigest.getInstance("MD5").digest(org.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "MD5(org)"; }
    }
    
    static class IvFromAppId implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            return MessageDigest.getInstance("MD5").digest(appId.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "MD5(appId)"; }
    }
    
    static class IvFromOrgAppId implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            String combined = org + ":" + appId;
            return MessageDigest.getInstance("MD5").digest(combined.getBytes(StandardCharsets.UTF_8));
        }
        public String getName() { return "MD5(org:appId)"; }
    }
    
    static class IvFromTimestampBytes implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            byte[] timestampBytes = new byte[8];
            for (int i = 7; i >= 0; i--) {
                timestampBytes[i] = (byte) (timestamp & 0xFF);
                timestamp >>= 8;
            }
            byte[] iv = new byte[16];
            System.arraycopy(timestampBytes, 0, iv, 0, 8);
            System.arraycopy(timestampBytes, 0, iv, 8, 8);
            return iv;
        }
        public String getName() { return "timestamp字节重复"; }
    }
    
    static class IvAllZeros implements IvDerivationStrategy {
        public byte[] deriveIv(long timestamp, String org, String appId, String fieldType) throws Exception {
            return new byte[16];
        }
        public String getName() { return "全零IV"; }
    }
    
    // ==================== 工具方法 ====================
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    
    private static double calculateEntropy(byte[] data) {
        int[] freq = new int[256];
        for (byte b : data) {
            freq[b & 0xFF]++;
        }
        double entropy = 0.0;
        int length = data.length;
        for (int count : freq) {
            if (count > 0) {
                double p = (double) count / length;
                entropy -= p * (Math.log(p) / Math.log(2));
            }
        }
        return entropy;
    }
    
    private static void printHexDump(String label, byte[] data, int maxLen) {
        System.out.println(label + ":");
        System.out.println("  长度: " + data.length + " 字节");
        System.out.println("  熵值: " + String.format("%.4f", calculateEntropy(data)));
        System.out.println("  前" + Math.min(maxLen, data.length) + "字节: " + 
            bytesToHex(Arrays.copyOf(data, Math.min(maxLen, data.length))));
    }
    
    // ==================== 解密方法 ====================
    
    /**
     * 解密 ep 字段（RSA-2048）
     */
    private static String decryptEp() {
        System.out.println("\n" + "=".repeat(80));
        System.out.println("步骤 1: 解密 ep 字段（RSA-2048）");
        System.out.println("=".repeat(80));
        
        try {
            // 1. 解码 Base64
            byte[] epBytes = Base64.getDecoder().decode(EP_ENCRYPTED);
            printHexDump("ep 解码后", epBytes, 32);
            
            // 2. 加载私钥
            byte[] privateKeyBytes = Base64.getDecoder().decode(PRIVATE_KEY_PEM);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            
            System.out.println("\n私钥信息:");
            System.out.println("  算法: " + privateKey.getAlgorithm());
            System.out.println("  格式: " + privateKey.getFormat());
            
            // 3. RSA 解密
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decrypted = cipher.doFinal(epBytes);
            
            System.out.println("\n✅ ep 解密成功！");
            System.out.println("=".repeat(80));
            printHexDump("解密后的数据", decrypted, 64);
            
            // 4. 尝试解析为字符串
            String decryptedStr = new String(decrypted, StandardCharsets.UTF_8);
            System.out.println("\n解密内容（文本）:");
            System.out.println(decryptedStr);
            
            return decryptedStr;
            
        } catch (Exception e) {
            System.out.println("\n❌ ep 解密失败: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 解密对称加密字段（tn 或 data）
     */
    private static String decryptSymmetricField(String fieldName, String encryptedBase64, 
                                               boolean hasCompression, X509Certificate cert) {
        System.out.println("\n" + "=".repeat(80));
        System.out.println("步骤: 解密 " + fieldName + " 字段（AES-CBC" + 
            (hasCompression ? " + zlib" : "") + "）");
        System.out.println("=".repeat(80));
        
        try {
            // 1. 解码 Base64
            byte[] encrypted = Base64.getDecoder().decode(encryptedBase64);
            printHexDump(fieldName + " 解码后", encrypted, 32);
            
            // 2. 准备所有密钥派生策略
            List<KeyDerivationStrategy> keyStrategies = Arrays.asList(
                new KeyFromPublicKeyDER(),
                new KeyFromRSAModulus(),
                new KeyFromCertFingerprint(),
                new KeyFromOrgAppId(),
                new KeyFromOrgOnly(),
                new KeyFromCombined(),
                new KeyFromCertBytes(),
                new KeyFromMD5Double()
            );
            
            // 3. 准备所有IV派生策略
            List<IvDerivationStrategy> ivStrategies = Arrays.asList(
                new IvFromTimestamp(),
                new IvFromTimestampField(),
                new IvFromTimestampOrg(),
                new IvFromOrg(),
                new IvFromAppId(),
                new IvFromOrgAppId(),
                new IvFromTimestampBytes(),
                new IvAllZeros()
            );
            
            int totalAttempts = keyStrategies.size() * ivStrategies.size();
            System.out.println("\n尝试 " + keyStrategies.size() + " 种密钥方案 × " + 
                ivStrategies.size() + " 种IV方案 = " + totalAttempts + " 种组合");
            System.out.println("-".repeat(80));
            
            int attempt = 0;
            
            // 4. 遍历所有组合
            for (KeyDerivationStrategy keyStrategy : keyStrategies) {
                byte[] key = keyStrategy.deriveKey(cert, ORGANIZATION, APP_ID);
                
                for (IvDerivationStrategy ivStrategy : ivStrategies) {
                    attempt++;
                    byte[] iv = ivStrategy.deriveIv(TIMESTAMP, ORGANIZATION, APP_ID, fieldName);
                    
                    try {
                        // AES 解密
                        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
                        IvParameterSpec ivSpec = new IvParameterSpec(iv);
                        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                        byte[] decrypted = cipher.doFinal(encrypted);
                        
                        // 如果需要解压缩
                        byte[] decompressed = decrypted;
                        if (hasCompression) {
                            try {
                                Inflater inflater = new Inflater(true); // true = nowrap (raw deflate)
                                inflater.setInput(decrypted);
                                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                                byte[] buffer = new byte[1024];
                                while (!inflater.finished()) {
                                    int count = inflater.inflate(buffer);
                                    baos.write(buffer, 0, count);
                                }
                                decompressed = baos.toByteArray();
                            } catch (Exception e) {
                                continue; // 解压缩失败，尝试下一个组合
                            }
                        }
                        
                        // 尝试解析为字符串
                        String result = new String(decompressed, StandardCharsets.UTF_8);
                        
                        // 验证是否是有效的文本（至少10个字符，且大部分可打印）
                        if (result.length() >= 10) {
                            long printableCount = result.chars()
                                .filter(c -> c >= 32 && c <= 126 || c == '\n' || c == '\r' || c == '\t')
                                .count();
                            if ((double)printableCount / result.length() > 0.8) {
                                System.out.println("\n✅ " + fieldName + " 解密成功！（尝试 " + 
                                    attempt + "/" + totalAttempts + "）");
                                System.out.println("=".repeat(80));
                                System.out.println("密钥方案: " + keyStrategy.getName());
                                System.out.println("密钥: " + bytesToHex(key));
                                System.out.println("IV方案: " + ivStrategy.getName());
                                System.out.println("IV: " + bytesToHex(iv));
                                System.out.println("\n解密内容:");
                                System.out.println(result);
                                return result;
                            }
                        }
                        
                    } catch (Exception e) {
                        // 静默忽略，继续下一个组合
                    }
                }
            }
            
            System.out.println("\n❌ " + fieldName + " 解密失败（尝试了 " + totalAttempts + " 种组合）");
            
        } catch (Exception e) {
            System.out.println("\n❌ " + fieldName + " 解密过程出错: " + e.getMessage());
            e.printStackTrace();
        }
        
        return null;
    }
    
    // ==================== 主函数 ====================
    
    public static void main(String[] args) {
        System.out.println("=".repeat(80));
        System.out.println("数美SDK完整解密器 - Java版本");
        System.out.println("基于真实返回值的反向工程");
        System.out.println("=".repeat(80));
        
        System.out.println("\n输入参数:");
        System.out.println("  organization: " + ORGANIZATION);
        System.out.println("  appId: " + APP_ID);
        System.out.println("  timestamp: " + TIMESTAMP);
        
        try {
            // 加载证书
            byte[] certBytes = Base64.getDecoder().decode(CERTIFICATE_BASE64);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(
                new ByteArra
                yInputStream(certBytes));
            
            System.out.println("\n证书信息:");
            System.out.println("  主题: " + cert.getSubjectX500Principal());
            System.out.println("  颁发者: " + cert.getIssuerX500Principal());
            System.out.println("  有效期: " + cert.getNotBefore() + " 至 " + cert.getNotAfter());
            System.out.println("  公钥算法: " + cert.getPublicKey().getAlgorithm());
            if (cert.getPublicKey() instanceof RSAPublicKey) {
                RSAPublicKey rsaKey = (RSAPublicKey) cert.getPublicKey();
                System.out.println("  RSA密钥大小: " + rsaKey.getModulus().bitLength() + " bits");
            }
            
            // 解密 ep（RSA）
            String epResult = decryptEp();
            
            // 解密 tn（AES）
            String tnResult = decryptSymmetricField("tn", TN_ENCRYPTED, false, cert);
            
            // 解密 data（AES + zlib）
            String dataResult = decryptSymmetricField("data", DATA_ENCRYPTED, true, cert);
            
            // 总结
            System.out.println("\n" + "=".repeat(80));
            System.out.println("解密结果总结");
            System.out.println("=".repeat(80));
            System.out.println("ep:   " + (epResult != null ? "✅ 成功" : "❌ 失败"));
            System.out.println("tn:   " + (tnResult != null ? "✅ 成功" : "❌ 失败"));
            System.out.println("data: " + (dataResult != null ? "✅ 成功" : "❌ 失败"));
            
            if (epResult != null || tnResult != null || dataResult != null) {
                System.out.println("\n💡 成功解密部分字段！");
                System.out.println("💡 请记录对应的密钥和IV方案，这是正确的加密方式。");
            } else {
                System.out.println("\n💡 所有尝试均失败，可能需要:");
                System.out.println("   1. 使用 Frida hook AES 函数获取实际的密钥和 IV");
                System.out.println("   2. 检查加密模式是否正确");
                System.out.println("   3. 检查填充方式");
            }
            
        } catch (Exception e) {
            System.out.println("\n❌ 程序执行失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

